package com.boil.qz.safekavass.service;

import com.boil.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ChenYong on 2017-08-01.
 * <br>
 * JpaRepository Service。
 * <br>
 * <p style="color: red; font-size: 20px;">
 * 注意：只有遵循 JPA 规范的实例对应的 Service 才能继承此类！！！
 * </p>
 */
public abstract class JpaRepositoryService<T, ID extends Serializable> {
    /**
     * 日志
     */
    protected static Logger log = LoggerFactory.getLogger(JpaRepositoryService.class);
    /**
     * 注入 JpaRepository
     */
    @Autowired
    protected JpaRepository<T, ID> jpaRepository;

    /**
     * 保存实例。
     *
     * @param entity 实例
     * @return 托管状态的实例
     */
    public <S extends T> S save(S entity) {
        if (entity == null) {
            return null;
        }

        return jpaRepository.save(entity);
    }

    /**
     * 保存实例集合 <code>Iterable</code>。
     *
     * @param entities 实例集合 <code>Iterable</code>
     * @return 托管状态的实例集合 <code>Iterable</code>
     */
    public <S extends T> Iterable<S> save(Iterable<S> entities) {
        if (entities == null) {
            return null;
        }

        return jpaRepository.save(entities);
    }

    /**
     * 强制保存实例。
     *
     * @param entity 实例
     * @return 托管状态的实例
     */
    public <S extends T> S saveAndFlush(S entity) {
        if (entity == null) {
            return null;
        }

        return jpaRepository.saveAndFlush(entity);
    }

    /**
     * 删除实例。
     *
     * @param id 主键，实例 ID
     */
    public void delete(ID id) {
        if (id != null) {
            jpaRepository.delete(id);
        }
    }

    /**
     * 删除托管状态的实例。
     *
     * @param entity 托管状态的实例
     */
    public void delete(T entity) {
        if (entity != null) {
            jpaRepository.delete(entity);
        }
    }

    /**
     * 删除所有实例。
     * <br>
     * <p style="color: red; font-size: 20px;">
     * 注意：谨慎调用此方法，一旦调用，将会清空表中所有数据！！！
     * </p>
     */
    public void deleteAll() {
        jpaRepository.deleteAll();
    }

    /**
     * 删除批处理中的实例集合 <code>Iterable</code>。
     *
     * @param iterable 批处理中的实例集合 <code>Iterable</code>
     */
    public void deleteInBatch(Iterable<T> iterable) {
        if (iterable != null) {
            jpaRepository.deleteInBatch(iterable);
        }
    }

    /**
     * 删除批处理中的所有实例。
     */
    public void deleteAllInBatch() {
        jpaRepository.deleteAllInBatch();
    }

    /**
     * 删除托管状态的实例集合 <code>Iterable</code>。
     *
     * @param entities 托管状态的实例集合 <code>Iterable</code>
     */
    public <S extends T> void delete(Iterable<S> entities) {
        if (entities != null) {
            jpaRepository.delete(entities);
        }
    }

    /**
     * 查询实例。
     *
     * @param id 主键，实例 ID
     * @return 托管状态的实例
     */
    public T findOne(ID id) {
        if (id == null) {
            return null;
        }

        return jpaRepository.findOne(id).orElse(null);
    }

    /**
     * 查询实例。
     *
     * @param example 实例例子
     * @return 托管状态的实例
     */
    public <S extends T> S findOne(Example<S> example) {
        if (example == null) {
            return null;
        }

        return jpaRepository.findOne(example);
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @return 托管状态的实例 <code>List</code>
     */
    public List<T> findAll() {
        return jpaRepository.findAll();
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @param iterable 主键 <code>Iterable</code>，实例 ID 集合 <code>Iterable</code>
     * @return 托管状态的实例 <code>List</code>
     */
    public List<T> findAll(Iterable<ID> iterable) {
        if (iterable == null) {
            return new ArrayList<T>();
        }

        return jpaRepository.findAll(iterable);
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @param example 实例例子
     * @return 托管状态的实例 <code>List</code>
     */
    public <S extends T> List<S> findAll(Example<S> example) {
        if (example == null) {
            return new ArrayList<S>();
        }

        return jpaRepository.findAll(example);
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @param sort 排序实例
     * @return 托管状态的实例 <code>List</code>。
     */
    public List<T> findAll(Sort sort) {
        if (sort == null) {
            return new ArrayList<T>();
        }

        return jpaRepository.findAll(sort);
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @param example 实例例子
     * @param sort    排序实例
     * @return 托管状态的实例 <code>List</code>
     */
    public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
        if ((example == null) || (sort == null)) {
            return new ArrayList<S>();
        }

        return jpaRepository.findAll(example, sort);
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @param pageable 分页实例
     * @return 托管状态的实例 <code>List</code>
     */
    public <S extends Sort> Page<T> findAll(Pageable pageable) {
        if (pageable == null) {
            return null;
        }

        return jpaRepository.findAll(pageable);
    }

    /**
     * 查询实例 <code>List</code>。
     *
     * @param example  实例例子
     * @param pageable 分页实例
     * @return 托管状态的实例 <code>List</code>
     */
    public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
        if ((example == null) || (pageable == null)) {
            return null;
        }

        return jpaRepository.findAll(example, pageable);
    }

    /**
     * 懒加载实例。
     *
     * @param id 主键，实例 ID
     * @return 托管状态的实例
     */
    public T getOne(ID id) {
        if (id == null) {
            return null;
        }

        return jpaRepository.getOne(id);
    }

    /**
     * 判断实例是否存在。
     *
     * @param id 主键，实例 ID
     * @return 实例是否存在：
     * <ol>
     * <li>true-存在；</li>
     * <li>false-不存在。</li>
     * </ol>
     */
    public boolean exists(ID id) {
        if (id == null) {
            return Constants.VALUE_FALSE;
        }

        return jpaRepository.exists(id);
    }

    /**
     * 判断实例是否存在。
     *
     * @param example 实例例子
     * @return 实例是否存在：
     * <ol>
     * <li>true-存在；</li>
     * <li>false-不存在。</li>
     * </ol>
     */
    public <S extends T> boolean exists(Example<S> example) {
        if (example == null) {
            return Constants.VALUE_FALSE;
        }

        return jpaRepository.exists(example);
    }

    /**
     * 统计实例个数。
     *
     * @return 实例个数
     */
    public long count() {
        return jpaRepository.count();
    }

    /**
     * 判断实例是否存在。
     *
     * @param example 实例例子
     * @return 实例个数
     */
    public <S extends T> long count(Example<S> example) {
        if (example == null) {
            return Constants.VALUE_L_0;
        }

        return jpaRepository.count(example);
    }

    /**
     * 同步数据库。
     */
    public void flush() {
        jpaRepository.flush();
    }
}